package fatworm.storage.table;

import fatworm.storage.file.*;
import fatworm.tx.*;
import fatworm.util.*;

/*
 * [EMPTY|INUSE, ISNULL, DATA]...
 */
public class TuplePage
{
    public static final byte EMPTY = 0, INUSE = 1;
    private Block blk;
    private TableInfo ti;
    private Transaction tx;
    private int slotsize;
    private int currentslot = -1;

    public TuplePage(Block blk, TableInfo ti, Transaction tx)
    {
        this.blk = blk;
        this.ti = ti;
        this.tx = tx;
        slotsize = ti.tupleLength() + 1;
        tx.pin(blk);
    }
    public void close()
    {
        if (blk != null)
        {
            tx.unpin(blk);
            blk = null;
        }
    }
    public boolean next()
    {
        return searchFor(INUSE);
    }
    public byte[] getBytes(String fldname)
    {
        int pos = curfieldpos(fldname);
        return tx.getBytes(blk, pos, ti.schema().type(fldname).lengthInTuplePage());
    }
    public void setBytes(String fldname, byte[] val)
    {
        int pos = curfieldpos(fldname);
        tx.setBytes(blk, pos, val);
    }
    public void delete()
    {
        int position = currentpos();
        tx.setBytes(blk, position, new byte[]{EMPTY});
    }
    public boolean insert()
    {
        currentslot = -1;
        boolean found = searchFor(EMPTY);
        if (found)
        {
            int position = currentpos();
            tx.setBytes(blk, position, new byte[]{INUSE});
        }
        return found;
    }
    public void moveToId(int id)
    {
        currentslot = id;
    }
    public int currentId()
    {
        return currentslot;
    }
    private int currentpos()
    {
        return currentslot * slotsize;
    }
    private int curfieldpos(String fldname)
    {
        int offset = 1 + ti.offset(fldname);
        return currentpos() + offset;
    }
    private boolean isValidSlot()
    {
        return currentpos() + slotsize <= Page.BLOCK_SIZE;
    }
    private boolean searchFor(byte flag)
    {
        currentslot++;
        while (isValidSlot())
        {
            int position = currentpos();
            Lib.debug("curpos: " + position);
            if (tx.getBytes(blk, position, 1)[0] == flag)
                return true;
            currentslot++;
        }
        return false;
    }
}
